package com.bjb.vr.common.service;

import cn.hutool.core.lang.UUID;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjb.vr.common.ao.UmsAccountAo;
import com.bjb.vr.common.constant.*;
import com.bjb.vr.common.dto.*;
import com.bjb.vr.common.mapper.*;
import com.bjb.vr.common.utils.JwtTokenUtil;
import com.bjb.vr.common.utils.RedisUtil;
import com.bjb.vr.common.utils.ThreadLocalUtil;
import com.bjb.vr.common.vo.UmsAccountVo;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * @author admin
 * @description 针对表【ums_account(后台账户表)】的数据库操作Service实现
 * @createDate 2022-03-18 18:00:07
 */
@Service
public class UmsAccountService extends ServiceImpl<UmsAccountMapper, UmsAccount> {

    private PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();

    @Resource
    private UmsAccountMapper umsAccountMapper;

    @Resource
    private UmsRoleMapper umsRoleMapper;

    @Resource
    private UmsUserRoleMapper umsUserRoleMapper;

    @Resource
    private SysTenantMapper sysTenantMapper;

    @Resource
    private SysConfigMapper sysConfigMapper;

    @Resource
    private SyncTenantMapper syncTenantMapper;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private SysDeptMapper sysDeptMapper;

    /**
     * 新增用户
     *
     * @param umsAccountAo
     * @return
     */
    public boolean saveUser(UmsAccountAo umsAccountAo) {
        Assert.hasText(umsAccountAo.getUserName(), "用户名不能为空");
        Assert.hasText(umsAccountAo.getPassword(), "密码不能为空");
        UmsAccount umsAccount = new UmsAccount();
        BeanUtils.copyProperties(umsAccountAo, umsAccount);
        umsAccount.setPassword(passwordEncoder.encode(umsAccountAo.getPassword()));
        umsAccount.setUsername(umsAccountAo.getUserName());
<<<<<<< HEAD
        umsAccount.setInitialPass(Constants.NO);
=======
>>>>>>> fd1f6b14a98acba5b7fb55a5f06eba006e6dbefb

        // 保存用户信息
        boolean result = this.save(umsAccount);

        // 更新用户角色信息
        if (umsAccountAo.getRoleId() != null) {
            UmsUserRole umsUserRole = new UmsUserRole();
            umsUserRole.setUserId(umsAccount.getUserId());
            umsUserRole.setRoleId(umsAccountAo.getRoleId());
            umsUserRoleMapper.insert(umsUserRole);
        }
        return result;
    }

    /**
     * 查询用户信息
     *
     * @param umsAccountAo
     * @return
     */
    public UmsAccountVo getAccountInfo(UmsAccountAo umsAccountAo) {
        // 开启放行
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, true);
        Claims claims = JwtTokenUtil.parseJWT(umsAccountAo.getAuthorization());
        String username = String.valueOf(claims.get(TokenConstants.TOKEN_USERNAME));

        // 查询缓存--教师端
        String refreshTokenId = SecureUtil.md5(username).toUpperCase();
        UmsAccount umsAccount = (UmsAccount) redisUtil.hget(TokenConstants.LOGIN_TOKEN_KEY + refreshTokenId, TokenConstants.TOKEN_USERNAME);

        // 查询数据库--教师端
        if (Objects.isNull(umsAccount)) {
            LambdaQueryWrapper<UmsAccount> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(StringUtils.isNotBlank(umsAccountAo.getUserName()), UmsAccount::getUsername, umsAccountAo.getUserName());
            queryWrapper.eq(StringUtils.isNotBlank(umsAccountAo.getAuthorization()), UmsAccount::getUsername, username);
            umsAccount = this.getOne(queryWrapper);
        }

        UmsAccountVo umsAccountVo = new UmsAccountVo();
        BeanUtils.copyProperties(umsAccount, umsAccountVo);
        umsAccountVo.setPassword("[PROTECTED]");
        umsAccountVo.setLoginType(LoginConstant.MANAGER);

        // 放入线程变量
        ThreadLocalUtil.set(ThreadLocalConstant.USER_ACCOUNT_INFO, umsAccountVo);

        // 关闭放行
        ThreadLocalUtil.set(ThreadLocalConstant.NO_TENANT_ID_VERIFY, false);
        return umsAccountVo;
    }

    /**
     * 更新用户登录信息
     *
     * @param username
     * @param loginTime
     */
    public void updateLoginTime(String username, LocalDateTime loginTime) {
        LambdaQueryWrapper<UmsAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(username), UmsAccount::getUsername, username);
        UmsAccount umsAccount = new UmsAccount();
        umsAccount.setLoginTime(loginTime);
        this.update(umsAccount, queryWrapper);
    }

    /**
     * 查询用户名或者昵称是否存在
     *
     * @param umsAccountAo
     */
    public List<UmsAccount> queryUserInfoByNameOrNickName(UmsAccountAo umsAccountAo) {
        List<UmsAccount> umsAccount = umsAccountMapper.queryUserInfoByNameOrNickName(umsAccountAo.getUserName(), umsAccountAo.getNickName());
        return umsAccount;
    }

    /**
     * 新增租户--教师端
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean addManagerTenant(UmsAccountAo umsAccountAo) {
        try {
            // 1、保存租户表
            UmsAccountVo threadLocalAccount = (UmsAccountVo) ThreadLocalUtil.get(ThreadLocalConstant.USER_ACCOUNT_INFO);
            String creator = threadLocalAccount.getUsername();
            String tenantIdNo = umsAccountAo.getTenantId();
            if (StringUtils.isBlank(tenantIdNo)) {
                tenantIdNo = UUID.fastUUID().toString().split("-")[4];
            }
            SysTenant sysTenant = new SysTenant();
            sysTenant.setTenantId(tenantIdNo);
            sysTenant.setTenantName(umsAccountAo.getTenantName());
            sysTenant.setParentId(umsAccountAo.getParentId());
            sysTenant.setCategory(umsAccountAo.getCategory());
            sysTenant.setAddressCode(umsAccountAo.getAddressCode());
            sysTenant.setAddress(umsAccountAo.getAddress());
            sysTenant.setEmail(umsAccountAo.getEmail());

            // 放入线程变量
            threadLocalAccount.setTempTenantId(tenantIdNo);
            ThreadLocalUtil.set(ThreadLocalConstant.USER_ACCOUNT_INFO, threadLocalAccount);
            sysTenantMapper.insert(sysTenant);

            // 2、保存sys_config表
            SysConfig sysConfig = new SysConfig();
            sysConfig.setTenantId(tenantIdNo);
            sysConfigMapper.insert(sysConfig);

            // 3、保存ums_account表、ums_role表、ums_user_role表，默认为管理员
            UmsAccount umsAccount = new UmsAccount();
            umsAccount.setTenantId(tenantIdNo);
            umsAccount.setUsername(umsAccountAo.getUserName());
            umsAccount.setPassword(passwordEncoder.encode(umsAccountAo.getPassword()));
            umsAccount.setNickName(umsAccountAo.getNickName());
            umsAccount.setSuperMan(RoleConstants.SUPER_IDENTIFY);
            umsAccountMapper.insert(umsAccount);

            UmsRole umsRole = new UmsRole();
            umsRole.setTenantId(tenantIdNo);
            umsRole.setRoleName(RoleConstants.SUPER_NAME);
            umsRole.setRoleKey(RoleConstants.SUPER_ADMIN);
            umsRole.setCreateBy(creator);
            umsRole.setRemark(RoleConstants.SUPER_NAME);
            umsRoleMapper.insert(umsRole);

            UmsUserRole userRole = new UmsUserRole();
            userRole.setUserId(umsAccount.getUserId());
            userRole.setRoleId(umsRole.getRoleId());
            userRole.setTenantId(tenantIdNo);
            umsUserRoleMapper.insert(userRole);

            // 4、判断是否需要开启同步
            if (umsAccountAo.getNeedSync()) {
                SyncTenant syncTenant = new SyncTenant();
                syncTenant.setTenantId(tenantIdNo);
                syncTenantMapper.insert(syncTenant);
            }

            // 5、添加到部门表中
            SysDept dept = new SysDept();
            dept.setTenantId(tenantIdNo);
            dept.setDeptName(sysTenant.getTenantName());
            dept.setLeaderId(umsAccount.getUserId());
            sysDeptMapper.insert(dept);
            return true;
        } catch (Exception e) {
            log.error("新增教师端租户失败...\n" + e.getMessage());
            return false;
        }
    }

    /**
     * 根据用户名查询账户信息
     *
     * @param userName
     * @return
     */
    public UmsAccount getAccountByUsername(String userName) {
        LambdaQueryWrapper<UmsAccount> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StringUtils.isNotBlank(userName), UmsAccount::getUsername, userName);
        UmsAccount umsAccount = umsAccountMapper.selectOne(queryWrapper);
        return umsAccount;
    }

}




